/*
 * circlebuff.c
 *
 *  Created on: 2023年6月29日
 *      Author: mcealt_DS
 */

#include "circular_buffer.h"
#include "em_core.h"
#include "sl_malloc.h"
#include "string.h"
bool bufferInit(Buffer_t *buffer, uint16_t size)
{
  bool bret = false;

  // Make sure we have enough room for this buffer
  if (size > CIRCULAR_BUFFER_LEN_MAX || buffer == NULL) {
    return false;
  }

  // Atomically initialize the buffer structure
  CORE_DECLARE_IRQ_STATE;
  CORE_ENTER_CRITICAL();
  buffer->data = sl_malloc(size);
  if(buffer->data){
      memset(buffer->data, 0, size);
      buffer->size = size;
      buffer->head = 0;
      buffer->count = 0;
      buffer->callback = NULL;
      bret = true;
  }else{

  }
  CORE_EXIT_CRITICAL();

  return bret;
}

bool bufferOverflow(Buffer_t *buffer, BufferOverflowCallback_t callback)
{
  buffer->callback = callback;
  return (callback != NULL);
}

bool bufferAdd(Buffer_t *buffer, uint8_t data)//voidu8, Todo 利用头尾指针 写一个高效circular buffer!
{
  // Do nothing if there's no buffer given
  if (buffer == NULL || !buffer->data) {
    return false;
  }
  bool added = true;

  CORE_DECLARE_IRQ_STATE;
  CORE_ENTER_CRITICAL();
  if (buffer->count < buffer->size) {
    uint16_t index = (buffer->head + buffer->count) % buffer->size; //若此处size为2^n 可以使用&位域操作来取余

    // Insert this item at the end of the buffer
    buffer->data[index] = data;
    buffer->count++;
  } else {
    // If an overflow callback exists, call it to see if the oldest bufferd
    // item is to be replaced (default) or not.
    if (buffer->callback != NULL) {
      added = buffer->callback(buffer, buffer->data[buffer->head]);
    }
    // Overwrite what's at the head of the buffer since we're out of space
    if (added) {
      buffer->data[buffer->head] = data;
      buffer->head = (buffer->head + 1) % buffer->size;
    }
  }
  CORE_EXIT_CRITICAL();

  return added;
}

uint8_t *bufferPeek(Buffer_t *buffer)
{
  uint8_t* ptr = NULL;

  // Do nothing if there's no buffer given
  if (buffer == NULL || !buffer->data) {
    return NULL;
  }

  CORE_DECLARE_IRQ_STATE;
  CORE_ENTER_CRITICAL();
  if (buffer->count > 0) {
    ptr = &buffer->data[buffer->head];
  }
  CORE_EXIT_CRITICAL();

  return ptr;
}

uint8_t *bufferRemove(Buffer_t *buffer)//Info 用指针返回的好处？
{
  uint8_t* ptr = NULL;

  // Do nothing if there's no buffer given
  if (buffer == NULL || !buffer->data) {
    return NULL;
  }

  CORE_DECLARE_IRQ_STATE;
  CORE_ENTER_CRITICAL();
  if (buffer->count > 0) {
    ptr = &buffer->data[buffer->head];
    buffer->head = (buffer->head + 1) % buffer->size;
    buffer->count--;
  }
  CORE_EXIT_CRITICAL();

  return ptr;
}

bool bufferIsEmpty(Buffer_t *buffer)
{
  bool result;

  if (buffer == NULL || !buffer->data) {
    return true;
  }

  CORE_DECLARE_IRQ_STATE;
  CORE_ENTER_CRITICAL();
  result = (buffer->count == 0);
  CORE_EXIT_CRITICAL();

  return result;
}

bool bufferIsFull(Buffer_t *buffer)
{
  bool result;

  if (buffer == NULL || !buffer->data) {
    return true;
  }

  CORE_DECLARE_IRQ_STATE;
  CORE_ENTER_CRITICAL();
  result = (buffer->count == buffer->size);
  CORE_EXIT_CRITICAL();

  return result;
}




